home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
gnu
/
gdb
/
gdb_18s.zoo
/
expread.y
< prev
next >
Wrap
Text File
|
1992-03-25
|
28KB
|
1,237 lines
/* Parse C expressions for GDB.
Copyright (C) 1986 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing.
Refer to the GDB General Public License for full details.
Everyone is granted permission to copy, modify and redistribute GDB,
but only under the conditions described in the GDB General Public
License. A copy of this license is supposed to have been given to you
along with GDB so you can know your rights and responsibilities. It
should be in a file named COPYING. Among other things, the copyright
notice and this notice must be preserved on all copies.
In other words, go ahead and share GDB, but don't try to stop
anyone else from sharing it farther. Help stamp out software hoarding!
*/
/* Parse a C expression from text in a string,
and return the result as a struct expression pointer.
That structure contains arithmetic operations in reverse polish,
with constants represented by operations that are followed by special data.
See expression.h for the details of the format.
What is important here is that it can be built up sequentially
during the process of parsing; the lower levels of the tree always
come first in the result. */
%{
#include "defs.h"
#include "param.h"
#include "symtab.h"
#include "frame.h"
#include "expression.h"
#include <stdio.h>
#ifdef atarist
extern int gcc_mshort;
#endif
extern CORE_ADDR end_of_text_addr;
static struct expression *expout;
static int expout_size;
static int expout_ptr;
static int yylex ();
static yyerror ();
static void write_exp_elt ();
static void write_exp_string ();
static void start_arglist ();
static int end_arglist ();
static void free_funcalls ();
static char *copy_name ();
/* If this is nonzero, this block is used as the lexical context
for symbol names. */
static struct block *expression_context_block;
/* Number of arguments seen so far in innermost function call. */
static int arglist_len;
/* Data structure for saving values of arglist_len
for function calls whose arguments contain other function calls. */
struct funcall
{
struct funcall *next;
int arglist_len;
};
struct funcall *funcall_chain;
/* This kind of datum is used to represent the name
of a symbol token. */
struct stoken
{
char *ptr;
int length;
};
%}
/* Although the yacc "value" of an expression is not used,
since the result is stored in the structure being created,
other node types do have values. */
%union
{
long lval;
double dval;
struct symbol *sym;
struct type *tval;
struct stoken sval;
int voidval;
struct block *bval;
enum exp_opcode opcode;
struct internalvar *ivar;
}
%type <voidval> exp exp1 start variable
%type <tval> type typebase
%type <bval> block
%token <lval> INT CHAR
%token <dval> FLOAT
/* Both NAME and TYPENAME tokens represent symbols in the input,
and both convey their data as strings.
But a TYPENAME is a string that happens to be defined as a typedef
or builtin type name (such as int or char)
and a NAME is any other symbol.
Contexts where this distinction is not important can use the
nonterminal "name", which matches either NAME or TYPENAME. */
%token <sval> NAME TYPENAME STRING
%type <sval> name
%token STRUCT UNION ENUM SIZEOF UNSIGNED COLONCOLON
%token <lval> LAST REGNAME
%token <ivar> VARIABLE
%token <opcode> ASSIGN_MODIFY
%left ','
%left ABOVE_COMMA
%right '=' ASSIGN_MODIFY
%right '?'
%left OR
%left AND
%left '|'
%left '^'
%left '&'
%left EQUAL NOTEQUAL
%left '<' '>' LEQ GEQ
%left LSH RSH
%left '+' '-'
%left '*' '/' '%'
%left '@'
%right UNARY INCREMENT DECREMENT
%right ARROW '.' '['
%left COLONCOLON
%%
start : exp1
;
/* Expressions, including the comma operator. */
exp1 : exp
| exp1 ',' exp
{ write_exp_elt (BINOP_COMMA); }
;
/* Expressions, not including the comma operator. */
exp : '*' exp %prec UNARY
{ write_exp_elt (UNOP_IND); }
exp : '&' exp %prec UNARY
{ write_exp_elt (UNOP_ADDR); }
exp : '-' exp %prec UNARY
{ write_exp_elt (UNOP_NEG); }
;
exp : '!' exp %prec UNARY
{ write_exp_elt (UNOP_ZEROP); }
;
exp : '~' exp %prec UNARY
{ write_exp_elt (UNOP_LOGNOT); }
;
exp : INCREMENT exp %prec UNARY
{ write_exp_elt (UNOP_PREINCREMENT); }
;
exp : DECREMENT exp %prec UNARY
{ write_exp_elt (UNOP_PREDECREMENT); }
;
exp : exp INCREMENT %prec UNARY
{ write_exp_elt (UNOP_POSTINCREMENT); }
;
exp : exp DECREMENT %prec UNARY
{ write_exp_elt (UNOP_POSTDECREMENT); }
;
exp : SIZEOF exp %prec UNARY
{ write_exp_elt (UNOP_SIZEOF); }
;
exp : exp ARROW name
{ write_exp_elt (STRUCTOP_PTR);
write_exp_string ($3);
write_exp_elt (STRUCTOP_PTR); }
;
exp : exp '.' name
{ write_exp_elt (STRUCTOP_STRUCT);
write_exp_string ($3);
write_exp_elt (STRUCTOP_STRUCT); }
;
exp : exp '[' exp1 ']'
{ write_exp_elt (BINOP_SUBSCRIPT); }
;
exp : exp '('
/* This is to save the value of arglist_len
being accumulated by an outer function call. */
{ start_arglist (); }
arglist ')' %prec ARROW
{ write_exp_elt (OP_FUNCALL);
write_exp_elt (end_arglist ());
write_exp_elt (OP_FUNCALL); }
;
arglist :
;
arglist : exp
{ arglist_len = 1; }
;
arglist : arglist ',' exp %prec ABOVE_COMMA
{ arglist_len++; }
;
exp : '{' type '}' exp %prec UNARY
{ write_exp_elt (UNOP_MEMVAL);
write_exp_elt ($2);
write_exp_elt (UNOP_MEMVAL); }
;
exp : '(' type ')' exp %prec UNARY
{ write_exp_elt (UNOP_CAST);
write_exp_elt ($2);
write_exp_elt (UNOP_CAST); }
;
exp : '(' exp1 ')'
{ }
;
/* Binary operators in order of decreasing precedence. */
exp : exp '@' exp
{ write_exp_elt (BINOP_REPEAT); }
;
exp : exp '*' exp
{ write_exp_elt (BINOP_MUL); }
;
exp : exp '/' exp
{ write_exp_elt (BINOP_DIV); }
;
exp : exp '%' exp
{ write_exp_elt (BINOP_REM); }
;
exp : exp '+' exp
{ write_exp_elt (BINOP_ADD); }
;
exp : exp '-' exp
{ write_exp_elt (BINOP_SUB); }
;
exp : exp LSH exp
{ write_exp_elt (BINOP_LSH); }
;
exp : exp RSH exp
{ write_exp_elt (BINOP_RSH); }
;
exp : exp EQUAL exp
{ write_exp_elt (BINOP_EQUAL); }
;
exp : exp NOTEQUAL exp
{ write_exp_elt (BINOP_NOTEQUAL); }
;
exp : exp LEQ exp
{ write_exp_elt (BINOP_LEQ); }
;
exp : exp GEQ exp
{ write_exp_elt (BINOP_GEQ); }
;
exp : exp '<' exp
{ write_exp_elt (BINOP_LESS); }
;
exp : exp '>' exp
{ write_exp_elt (BINOP_GTR); }
;
exp : exp '&' exp
{ write_exp_elt (BINOP_LOGAND); }
;
exp : exp '^' exp
{ write_exp_elt (BINOP_LOGXOR); }
;
exp : exp '|' exp
{ write_exp_elt (BINOP_LOGIOR); }
;
exp : exp AND exp
{ write_exp_elt (BINOP_AND); }
;
exp : exp OR exp
{ write_exp_elt (BINOP_OR); }
;
exp : exp '?' exp ':' exp %prec '?'
{ write_exp_elt (TERNOP_COND); }
;
exp : exp '=' exp
{ write_exp_elt (BINOP_ASSIGN); }
;
exp : exp ASSIGN_MODIFY exp
{ write_exp_elt (BINOP_ASSIGN_MODIFY);
write_exp_elt ($2);
write_exp_elt (BINOP_ASSIGN_MODIFY); }
;
exp : INT
{ write_exp_elt (OP_LONG);
#if 0
if(gcc_mshort)
write_exp_elt (builtin_type_short);
else
#endif
write_exp_elt (builtin_type_int);
write_exp_elt ($1);
write_exp_elt (OP_LONG); }
;
exp : CHAR
{ write_exp_elt (OP_LONG);
write_exp_elt (builtin_type_char);
write_exp_elt ($1);
write_exp_elt (OP_LONG); }
;
exp : FLOAT
{ write_exp_elt (OP_DOUBLE);
write_exp_elt (builtin_type_double);
write_exp_elt ($1);
write_exp_elt (OP_DOUBLE); }
;
exp : variable
;
exp : LAST
{ write_exp_elt (OP_LAST);
write_exp_elt ($1);
write_exp_elt (OP_LAST); }
;
exp : REGNAME
{ write_exp_elt (OP_REGISTER);
write_exp_elt ($1);
write_exp_elt (OP_REGISTER); }
;
exp : VARIABLE
{ write_exp_elt (OP_INTERNALVAR);
write_exp_elt ($1);
write_exp_elt (OP_INTERNALVAR); }
;
exp : SIZEOF '(' type ')'